import { 
  CANVAS_CONFIG, 
  PARTICIPANT_COLORS,
  COLOR_MAP 
} from './constants.js'
import { 
  getElementWidth, 
  getElementHeight, 
  getElementCenter,
  getElementEdgePoint,
  getParticipantColors,
  getColorValue,
  getVisibilitySymbol
} from './utils.js'

/**
 * 绘制圆角矩形
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 * @param {number} radius - 圆角半径
 */
export function drawRoundedRectangle(ctx, x, y, width, height, radius) {
  ctx.beginPath()
  ctx.moveTo(x + radius, y)
  ctx.lineTo(x + width - radius, y)
  ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
  ctx.lineTo(x + width, y + height - radius)
  ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height)
  ctx.lineTo(x + radius, y + height)
  ctx.quadraticCurveTo(x, y + height, x, y + height - radius)
  ctx.lineTo(x, y + radius)
  ctx.quadraticCurveTo(x, y, x + radius, y)
  ctx.closePath()
}

/**
 * 绘制选中框
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 */
export function drawSelectionBox(ctx, x, y, width, height) {
  ctx.strokeStyle = '#1890ff'
  ctx.lineWidth = 2
  ctx.setLineDash([5, 5])
  ctx.strokeRect(x - CANVAS_CONFIG.SELECTION_PADDING, y - CANVAS_CONFIG.SELECTION_PADDING, 
                width + CANVAS_CONFIG.SELECTION_PADDING * 2, height + CANVAS_CONFIG.SELECTION_PADDING * 2)
  ctx.setLineDash([])
  
  // 绘制选中框的四个角
  const cornerSize = 8
  ctx.fillStyle = '#1890ff'
  ctx.fillRect(x - CANVAS_CONFIG.SELECTION_PADDING, y - CANVAS_CONFIG.SELECTION_PADDING, cornerSize, cornerSize)
  ctx.fillRect(x + width - CANVAS_CONFIG.SELECTION_PADDING, y - CANVAS_CONFIG.SELECTION_PADDING, cornerSize, cornerSize)
  ctx.fillRect(x - CANVAS_CONFIG.SELECTION_PADDING, y + height - CANVAS_CONFIG.SELECTION_PADDING, cornerSize, cornerSize)
  ctx.fillRect(x + width - CANVAS_CONFIG.SELECTION_PADDING, y + height - CANVAS_CONFIG.SELECTION_PADDING, cornerSize, cornerSize)
}

/**
 * 绘制连接点
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} element - 元素对象
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 */
export function drawConnectionPoints(ctx, element, x, y, width, height) {
  const pointRadius = CANVAS_CONFIG.CONNECTION_POINT_RADIUS
  const points = [
    { x: x + width / 2, y: y - pointRadius, side: 'top' },
    { x: x + width + pointRadius, y: y + height / 2, side: 'right' },
    { x: x + width / 2, y: y + height + pointRadius, side: 'bottom' },
    { x: x - pointRadius, y: y + height / 2, side: 'left' }
  ]
  
  points.forEach(point => {
    ctx.save()
    ctx.fillStyle = '#1890ff'
    ctx.strokeStyle = '#ffffff'
    ctx.lineWidth = 2
    
    ctx.beginPath()
    ctx.arc(point.x, point.y, pointRadius, 0, 2 * Math.PI)
    ctx.fill()
    ctx.stroke()
    ctx.restore()
  })
}

/**
 * 绘制箭头
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - 箭头尖端x坐标
 * @param {number} y - 箭头尖端y坐标
 * @param {number} fromX - 起始x坐标
 * @param {number} fromY - 起始y坐标
 * @param {string} type - 关系类型
 */
export function drawArrow(ctx, x, y, fromX, fromY, type, color = '#333') {
  const angle = Math.atan2(y - fromY, x - fromX)
  const arrowLength = 15
  const arrowAngle = Math.PI / 6
  
  ctx.save()
  ctx.translate(x, y)
  ctx.rotate(angle)
  
  ctx.beginPath()
  ctx.moveTo(0, 0)
  ctx.lineTo(-arrowLength, -arrowLength * Math.tan(arrowAngle))
  ctx.lineTo(-arrowLength, arrowLength * Math.tan(arrowAngle))
  ctx.closePath()
  
  if (type === 'composition') {
    ctx.fillStyle = color
    ctx.fill()
  } else if (type === 'aggregation') {
    ctx.strokeStyle = color
    ctx.lineWidth = 2
    ctx.stroke()
  } else {
    ctx.fillStyle = color
    ctx.fill()
  }
  
  ctx.restore()
}

/**
 * 绘制网格
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} width - 画布宽度
 * @param {number} height - 画布高度
 * @param {number} translateX - 平移x
 * @param {number} translateY - 平移y
 */
export function drawGrid(ctx, width, height, translateX, translateY) {
  const gridSize = CANVAS_CONFIG.GRID_SIZE
  const offsetX = translateX % gridSize
  const offsetY = translateY % gridSize
  
  ctx.save()
  ctx.strokeStyle = 'rgba(0,0,0,0.1)'
  ctx.lineWidth = 1
  
  // 绘制垂直线
  for (let x = offsetX; x < width; x += gridSize) {
    ctx.beginPath()
    ctx.moveTo(x, 0)
    ctx.lineTo(x, height)
    ctx.stroke()
  }
  
  // 绘制水平线
  for (let y = offsetY; y < height; y += gridSize) {
    ctx.beginPath()
    ctx.moveTo(0, y)
    ctx.lineTo(width, y)
    ctx.stroke()
  }
  
  ctx.restore()
}

/**
 * 绘制活动元素
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} element - 元素对象
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 */
export function drawActivityElement(ctx, element, x, y, width, height) {
  // 根据元素颜色或选择状态创建渐变
  let gradient
  if (element.color) {
    const color = getColorValue(element.color)
    gradient = ctx.createLinearGradient(x, y, x, y + height)
    gradient.addColorStop(0, color)
    gradient.addColorStop(1, color)
  } else if (element.selected) {
    gradient = ctx.createLinearGradient(x, y, x, y + height)
    gradient.addColorStop(0, '#e6f7ff')
    gradient.addColorStop(1, '#bae7ff')
  } else {
    gradient = ctx.createLinearGradient(x, y, x, y + height)
    gradient.addColorStop(0, '#ffffff')
    gradient.addColorStop(1, '#f5f5f5')
  }
  
  ctx.fillStyle = gradient
  
  switch (element.activityType) {
    case 'start':
    case 'end':
      // 绘制圆形
      ctx.beginPath()
      ctx.arc(x + width / 2, y + height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI)
      ctx.fill()
      ctx.strokeStyle = element.selected ? '#1890ff' : '#d9d9d9'
      ctx.lineWidth = element.selected ? 3 : 1
      ctx.stroke()
      break
      
    case 'decision':
    case 'condition':
      // 绘制菱形
      ctx.beginPath()
      ctx.moveTo(x + width / 2, y)
      ctx.lineTo(x + width, y + height / 2)
      ctx.lineTo(x + width / 2, y + height)
      ctx.lineTo(x, y + height / 2)
      ctx.closePath()
      ctx.fill()
      ctx.strokeStyle = element.selected ? '#1890ff' : '#d9d9d9'
      ctx.lineWidth = element.selected ? 3 : 1
      ctx.stroke()
      break
      
    case 'merge':
    case 'join':
      // 绘制倒三角形
      ctx.beginPath()
      ctx.moveTo(x + width / 2, y)
      ctx.lineTo(x + width, y + height)
      ctx.lineTo(x, y + height)
      ctx.closePath()
      ctx.fill()
      ctx.strokeStyle = element.selected ? '#1890ff' : '#d9d9d9'
      ctx.lineWidth = element.selected ? 3 : 1
      ctx.stroke()
      break
      
    case 'fork':
      // 绘制正三角形
      ctx.beginPath()
      ctx.moveTo(x + width / 2, y + height)
      ctx.lineTo(x + width, y)
      ctx.lineTo(x, y)
      ctx.closePath()
      ctx.fill()
      ctx.strokeStyle = element.selected ? '#1890ff' : '#d9d9d9'
      ctx.lineWidth = element.selected ? 3 : 1
      ctx.stroke()
      break
      
    default:
      // 绘制圆角矩形（默认）
      drawRoundedRectangle(ctx, x, y, width, height, 8)
      ctx.fill()
      ctx.strokeStyle = element.selected ? '#1890ff' : '#d9d9d9'
      ctx.lineWidth = element.selected ? 3 : 1
      ctx.stroke()
  }
}

/**
 * 绘制生命线元素
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} element - 元素对象
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 */
export function drawLifelineElement(ctx, element, x, y, width, height) {
  const participantType = element.participantType || 'participant'
  const colors = getParticipantColors(participantType, element.selected)
  
  // 创建渐变
  const gradient = ctx.createLinearGradient(x, y, x, y + height)
  gradient.addColorStop(0, colors.gradient[0])
  gradient.addColorStop(1, colors.gradient[1])
  
  ctx.fillStyle = gradient
  
  // 绘制圆角矩形背景
  drawRoundedRectangle(ctx, x, y, width, height, 12)
  ctx.fill()
  
  // 绘制边框
  ctx.strokeStyle = element.selected ? '#1890ff' : colors.stroke
  ctx.lineWidth = element.selected ? 3 : 2
  ctx.stroke()
  
  // 绘制参与者图标
  const iconSize = Math.min(width, height) * 0.3
  const iconX = x + width / 2
  const iconY = y + height * 0.3
  
  ctx.fillStyle = colors.icon
  ctx.strokeStyle = colors.icon
  ctx.lineWidth = 2
  
  switch (participantType) {
    case 'actor':
      drawActorIcon(ctx, iconX, iconY, iconSize)
      break
    case 'database':
      drawDatabaseIcon(ctx, iconX, iconY, iconSize)
      break
    case 'boundary':
      drawBoundaryIcon(ctx, iconX, iconY, iconSize)
      break
    case 'control':
      drawControlIcon(ctx, iconX, iconY, iconSize)
      break
    case 'entity':
      drawEntityIcon(ctx, iconX, iconY, iconSize)
      break
    default:
      drawDefaultIcon(ctx, iconX, iconY, iconSize)
  }
  
  // 绘制生命线（垂直线）
  const lifelineX = x + width / 2
  const lifelineY = y + height
  
  ctx.strokeStyle = element.selected ? '#1890ff' : '#666666'
  ctx.lineWidth = element.selected ? 3 : 2
  ctx.setLineDash([5, 5])
  ctx.beginPath()
  ctx.moveTo(lifelineX, lifelineY)
  ctx.lineTo(lifelineX, lifelineY + CANVAS_CONFIG.LIFELINE_LENGTH)
  ctx.stroke()
  ctx.setLineDash([])
  
  // 绘制生命线底部的实心圆
  ctx.fillStyle = element.selected ? '#1890ff' : '#666666'
  ctx.beginPath()
  ctx.arc(lifelineX, lifelineY + CANVAS_CONFIG.LIFELINE_LENGTH, 4, 0, 2 * Math.PI)
  ctx.fill()
}

/**
 * 绘制人形图标
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} size - 图标大小
 */
export function drawActorIcon(ctx, x, y, size) {
  // 头部
  ctx.beginPath()
  ctx.arc(x, y - size * 0.3, size * 0.2, 0, 2 * Math.PI)
  ctx.fill()
  
  // 身体
  ctx.beginPath()
  ctx.moveTo(x, y - size * 0.1)
  ctx.lineTo(x, y + size * 0.3)
  ctx.stroke()
  
  // 手臂
  ctx.beginPath()
  ctx.moveTo(x - size * 0.3, y)
  ctx.lineTo(x + size * 0.3, y)
  ctx.stroke()
  
  // 腿部
  ctx.beginPath()
  ctx.moveTo(x, y + size * 0.3)
  ctx.lineTo(x - size * 0.2, y + size * 0.5)
  ctx.moveTo(x, y + size * 0.3)
  ctx.lineTo(x + size * 0.2, y + size * 0.5)
  ctx.stroke()
}

/**
 * 绘制数据库图标
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} size - 图标大小
 */
export function drawDatabaseIcon(ctx, x, y, size) {
  // 数据库主体
  ctx.beginPath()
  ctx.ellipse(x, y - size * 0.2, size * 0.3, size * 0.15, 0, 0, 2 * Math.PI)
  ctx.fill()
  
  // 数据库底部
  ctx.beginPath()
  ctx.ellipse(x, y + size * 0.2, size * 0.3, size * 0.15, 0, 0, 2 * Math.PI)
  ctx.fill()
  
  // 连接线
  ctx.beginPath()
  ctx.moveTo(x - size * 0.3, y - size * 0.2)
  ctx.lineTo(x - size * 0.3, y + size * 0.2)
  ctx.moveTo(x + size * 0.3, y - size * 0.2)
  ctx.lineTo(x + size * 0.3, y + size * 0.2)
  ctx.stroke()
}

/**
 * 绘制边界图标
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} size - 图标大小
 */
export function drawBoundaryIcon(ctx, x, y, size) {
  // 边界框
  ctx.strokeRect(x - size * 0.25, y - size * 0.25, size * 0.5, size * 0.5)
  
  // 内部装饰
  ctx.beginPath()
  ctx.moveTo(x - size * 0.15, y)
  ctx.lineTo(x + size * 0.15, y)
  ctx.stroke()
}

/**
 * 绘制控制图标
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} size - 图标大小
 */
export function drawControlIcon(ctx, x, y, size) {
  // 控制图标（齿轮形状）
  const radius = size * 0.2
  const teeth = 8
  const innerRadius = radius * 0.6
  
  ctx.beginPath()
  for (let i = 0; i < teeth; i++) {
    const angle = (i * 2 * Math.PI) / teeth
    const nextAngle = ((i + 1) * 2 * Math.PI) / teeth
    const midAngle = (angle + nextAngle) / 2
    
    if (i === 0) {
      ctx.moveTo(x + radius * Math.cos(angle), y + radius * Math.sin(angle))
    } else {
      ctx.lineTo(x + radius * Math.cos(angle), y + radius * Math.sin(angle))
    }
    
    ctx.lineTo(x + innerRadius * Math.cos(midAngle), y + innerRadius * Math.sin(midAngle))
  }
  ctx.closePath()
  ctx.fill()
}

/**
 * 绘制实体图标
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} size - 图标大小
 */
export function drawEntityIcon(ctx, x, y, size) {
  // 实体图标（立方体）
  const halfSize = size * 0.2
  
  ctx.beginPath()
  // 前面
  ctx.moveTo(x - halfSize, y - halfSize)
  ctx.lineTo(x + halfSize, y - halfSize)
  ctx.lineTo(x + halfSize, y + halfSize)
  ctx.lineTo(x - halfSize, y + halfSize)
  ctx.closePath()
  ctx.fill()
  
  // 侧面
  ctx.beginPath()
  ctx.moveTo(x + halfSize, y - halfSize)
  ctx.lineTo(x + halfSize * 1.5, y - halfSize * 0.5)
  ctx.lineTo(x + halfSize * 1.5, y + halfSize * 0.5)
  ctx.lineTo(x + halfSize, y + halfSize)
  ctx.closePath()
  ctx.fill()
  
  // 顶面
  ctx.beginPath()
  ctx.moveTo(x - halfSize, y - halfSize)
  ctx.lineTo(x - halfSize * 0.5, y - halfSize * 1.5)
  ctx.lineTo(x + halfSize * 0.5, y - halfSize * 1.5)
  ctx.lineTo(x + halfSize, y - halfSize)
  ctx.closePath()
  ctx.fill()
}

/**
 * 绘制默认图标
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} size - 图标大小
 */
export function drawDefaultIcon(ctx, x, y, size) {
  // 默认图标（圆形）
  ctx.beginPath()
  ctx.arc(x, y, size * 0.2, 0, 2 * Math.PI)
  ctx.fill()
}

/**
 * 绘制元素内容
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} element - 元素对象
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 */
export function drawElementContent(ctx, element, x, y, width, height) {
  // 绘制标题栏
  const titleHeight = 30
  const titleGradient = ctx.createLinearGradient(x, y, x, y + titleHeight)
  if (element.selected) {
    titleGradient.addColorStop(0, '#1890ff')
    titleGradient.addColorStop(1, '#096dd9')
  } else {
    titleGradient.addColorStop(0, '#f0f0f0')
    titleGradient.addColorStop(1, '#d9d9d9')
  }
  
  ctx.fillStyle = titleGradient
  
  // 根据元素类型绘制不同的标题栏
  if (element.type === 'activity' && (element.activityType === 'start' || element.activityType === 'end' || element.activityType === 'decision' || element.activityType === 'condition')) {
    // 对于特殊形状的元素，不绘制标题栏
  } else if (element.type === 'lifeline') {
    // 对于lifeline元素，不绘制标题栏，因为已经有图标了
  } else if (element.type === 'state' || element.type === 'usecase') {
    // 对于状态图和用例图元素，不在这里绘制标题栏，因为有专门的绘制函数
  } else {
    // 绘制圆角矩形标题栏
    const radius = 8
    ctx.beginPath()
    ctx.moveTo(x + radius, y)
    ctx.lineTo(x + width - radius, y)
    ctx.quadraticCurveTo(x + width, y, x + width, y + radius)
    ctx.lineTo(x + width, y + titleHeight)
    ctx.lineTo(x, y + titleHeight)
    ctx.lineTo(x, y + radius)
    ctx.quadraticCurveTo(x, y, x + radius, y)
    ctx.closePath()
    ctx.fill()
  }
  
  // 绘制标题文本
  ctx.fillStyle = element.selected ? '#ffffff' : '#333333'
  ctx.font = 'bold 14px Arial'
  ctx.textAlign = 'center'
  
  if (element.type === 'activity' && (element.activityType === 'start' || element.activityType === 'end' || element.activityType === 'decision' || element.activityType === 'condition')) {
    // 对于特殊形状的元素，在中心绘制文本
    ctx.fillText(element.name, x + width / 2, y + height / 2 + 5)
  } else if (element.type === 'lifeline') {
    // 对于lifeline元素，在底部绘制文本
    ctx.fillStyle = element.selected ? '#1890ff' : '#333333'
    ctx.fillText(element.name, x + width / 2, y + height - 10)
  } else if (element.type === 'state' || element.type === 'usecase') {
    // 对于状态图和用例图元素，不在这里绘制文本，因为有专门的绘制函数
  } else {
    // 对于普通元素，在标题栏绘制文本
    ctx.fillText(element.name, x + width / 2, y + 20)
  }
  
  // 绘制元素内容
  if (element.type === 'state' || element.type === 'usecase') {
    // 状态图和用例图元素的内容由专门的绘制函数处理
  } else if (element.attributes && element.attributes.length > 0) {
    ctx.font = '12px Arial'
    ctx.textAlign = 'left'
    ctx.fillStyle = '#333333'
    let contentY = y + titleHeight + 15
    element.attributes.forEach((attr, index) => {
      const text = `${getVisibilitySymbol(attr.visibility)} ${attr.name}: ${attr.type}`
      ctx.fillText(text, x + 10, contentY)
      contentY += 18
    })
  }
  
  if (element.type === 'state' || element.type === 'usecase') {
    // 状态图和用例图元素的方法由专门的绘制函数处理
  } else if (element.methods && element.methods.length > 0) {
    ctx.font = '12px Arial'
    ctx.textAlign = 'left'
    ctx.fillStyle = '#333333'
    let contentY = y + titleHeight + (element.attributes ? element.attributes.length * 18 + 15 : 15)
    element.methods.forEach((method, index) => {
      const text = `${getVisibilitySymbol(method.visibility)} ${method.name}(): ${method.returnType}`
      ctx.fillText(text, x + 10, contentY)
      contentY += 18
    })
  }
}

/**
 * 绘制关系线
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} relationship - 关系对象
 * @param {Object} source - 源元素
 * @param {Object} target - 目标元素
 */
export function drawRelationship(ctx, relationship, source, target) {
  const start = getElementEdgePoint(getElementCenter(target), getElementCenter(source), source, 'source')
  const end = getElementEdgePoint(getElementCenter(source), getElementCenter(target), target, 'target')
  
  // 检查坐标是否有效
  if (isNaN(start.x) || isNaN(start.y) || isNaN(end.x) || isNaN(end.y)) {
    console.warn('Invalid coordinates for relationship:', relationship, start, end)
    return
  }
  
  ctx.save()

  // 根据上下文(元素类型)决定风格
  const sameType = source.type === target.type ? source.type : null
  let stroke = relationship.selected ? '#1890ff' : '#333'
  let dash = []
  let arrowColor = stroke

  if (sameType === 'activity') {
    if (relationship.relationshipType === 'dependency') {
      // 数据流：橙色虚线
      stroke = '#fa8c16'
      arrowColor = '#fa8c16'
      dash = [5, 3]
      ctx.lineWidth = relationship.selected ? 4 : 2
    } else {
      // 控制流：蓝色实线
      stroke = '#2f54eb'
      arrowColor = '#2f54eb'
      dash = []
      ctx.lineWidth = relationship.selected ? 4 : 3
    }
  } else if (sameType === 'lifeline') {
    if (relationship.relationshipType === 'dependency') {
      stroke = '#737373'
      arrowColor = '#737373'
      dash = [3, 3]
    } else {
      stroke = '#333'
      arrowColor = '#333'
      dash = []
    }
  } else {
    // 类图/用例/状态图的默认风格
    if (relationship.relationshipType === 'inheritance') {
      dash = [10, 5]
    } else if (relationship.relationshipType === 'implementation') {
      dash = [5, 5]
    } else if (relationship.relationshipType === 'dependency') {
      dash = [3, 3]
    } else {
      dash = []
    }
  }

  // 增强关系线的可见性
  ctx.strokeStyle = stroke
  // 线宽已在各类型中设置，这里仅设置默认值
  if (!ctx.lineWidth) {
    ctx.lineWidth = relationship.selected ? 4 : 3
  }
  
  // 添加阴影效果
  ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'
  ctx.shadowBlur = 4
  ctx.shadowOffsetX = 2
  ctx.shadowOffsetY = 2
  
  // 绘制线条
  ctx.setLineDash(dash)
  
  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(end.x, end.y)
  ctx.stroke()
  
  // 重置阴影
  ctx.shadowColor = 'transparent'
  ctx.shadowBlur = 0
  ctx.shadowOffsetX = 0
  ctx.shadowOffsetY = 0
  
  // 如果线条被选中，绘制选中效果
  if (relationship.selected) {
    ctx.strokeStyle = '#1890ff'
    ctx.lineWidth = 1
    ctx.setLineDash([3, 3])
    
    const padding = 8
    const minX = Math.min(start.x, end.x) - padding
    const maxX = Math.max(start.x, end.x) + padding
    const minY = Math.min(start.y, end.y) - padding
    const maxY = Math.max(start.y, end.y) + padding
    
    ctx.strokeRect(minX, minY, maxX - minX, maxY - minY)
    ctx.setLineDash([])
  }
  
  // 绘制箭头
  drawArrow(ctx, end.x, end.y, start.x, start.y, relationship.relationshipType, arrowColor)
  
  ctx.restore()
}

/**
 * 绘制高亮的执行路径关系线（支持部分进度与动态虚线偏移）
 * @param {CanvasRenderingContext2D} ctx
 * @param {Object} relationship
 * @param {Object} source
 * @param {Object} target
 * @param {number} progress 0..1 绘制进度
 * @param {number} dashOffset 虚线偏移（动画）
 */
export function drawHighlightedRelationship(ctx, relationship, source, target, progress = 1, dashOffset = 0) {
  const start = getElementEdgePoint(getElementCenter(target), getElementCenter(source), source, 'source')
  const end = getElementEdgePoint(getElementCenter(source), getElementCenter(target), target, 'target')
  if (isNaN(start.x) || isNaN(start.y) || isNaN(end.x) || isNaN(end.y)) return

  const dx = end.x - start.x
  const dy = end.y - start.y
  const px = start.x + dx * Math.max(0, Math.min(1, progress))
  const py = start.y + dy * Math.max(0, Math.min(1, progress))

  ctx.save()
  ctx.strokeStyle = '#52c41a'
  ctx.lineWidth = 5
  ctx.shadowColor = 'rgba(82, 196, 26, 0.6)'
  ctx.shadowBlur = 10
  ctx.setLineDash([14, 10])
  ctx.lineDashOffset = -dashOffset

  ctx.beginPath()
  ctx.moveTo(start.x, start.y)
  ctx.lineTo(px, py)
  ctx.stroke()

  // 箭头
  drawArrow(ctx, px, py, start.x, start.y, relationship.relationshipType, '#52c41a')

  ctx.restore()
}

/**
 * 高亮元素边框（执行过的节点）
 */
export function drawElementHighlight(ctx, x, y, width, height) {
  ctx.save()
  ctx.strokeStyle = '#52c41a'
  ctx.lineWidth = 3
  ctx.shadowColor = 'rgba(82, 196, 26, 0.6)'
  ctx.shadowBlur = 12
  drawRoundedRectangle(ctx, x, y, width, height, 10)
  ctx.stroke()
  ctx.restore()
}

/**
 * 绘制类/接口/枚举元素（优雅样式）
 */
export function drawClassElement(ctx, element, x, y, width, height) {
  // 外框与阴影
  ctx.save()
  ctx.shadowColor = 'rgba(0, 0, 0, 0.12)'
  ctx.shadowBlur = 6
  ctx.shadowOffsetX = 2
  ctx.shadowOffsetY = 2
  drawRoundedRectangle(ctx, x, y, width, height, 10)
  ctx.fillStyle = '#ffffff'
  ctx.fill()
  ctx.shadowColor = 'transparent'
  ctx.shadowBlur = 0

  // 顶部标题栏渐变
  const titleHeight = 34
  const grad = ctx.createLinearGradient(x, y, x, y + titleHeight)
  grad.addColorStop(0, '#f7f9fc')
  grad.addColorStop(1, '#eef2f7')
  ctx.fillStyle = grad
  ctx.beginPath()
  ctx.moveTo(x + 10, y)
  ctx.lineTo(x + width - 10, y)
  ctx.quadraticCurveTo(x + width, y, x + width, y + 10)
  ctx.lineTo(x + width, y + titleHeight)
  ctx.lineTo(x, y + titleHeight)
  ctx.lineTo(x, y + 10)
  ctx.quadraticCurveTo(x, y, x + 10, y)
  ctx.closePath()
  ctx.fill()

  // 外边框
  ctx.strokeStyle = '#cfd7e6'
  ctx.lineWidth = 1.5
  drawRoundedRectangle(ctx, x, y, width, height, 10)
  ctx.stroke()

  // 标题文本
  ctx.fillStyle = '#1f2937'
  ctx.font = '600 14px Inter, Arial'
  ctx.textAlign = 'center'
  ctx.textBaseline = 'middle'
  let title = element.name || ''
  if (element.type === 'interface') {
    title = `«interface»\n${element.name || ''}`
  } else if (element.type === 'enum') {
    title = `«enum»\n${element.name || ''}`
  }
  const titleLines = title.split('\n')
  const titleYStart = y + titleHeight / 2 - (titleLines.length - 1) * 8
  titleLines.forEach((line, idx) => {
    ctx.fillText(line, x + width / 2, titleYStart + idx * 16)
  })

  // 分隔线
  ctx.strokeStyle = '#e5eaf2'
  ctx.lineWidth = 1
  ctx.beginPath()
  ctx.moveTo(x, y + titleHeight + 0.5)
  ctx.lineTo(x + width, y + titleHeight + 0.5)
  ctx.stroke()

  // 内容区（溢出截断 + 省略号）
  ctx.fillStyle = '#374151'
  ctx.font = '12px Menlo, Consolas, monospace'
  ctx.textAlign = 'left'
  let cursorY = y + titleHeight + 16
  const contentPaddingX = 10
  const maxContentWidth = width - contentPaddingX * 2
  const ellipsis = '…'
  const truncate = (text) => {
    if (ctx.measureText(text).width <= maxContentWidth) return text
    let low = 0, high = text.length
    while (low < high) {
      const mid = Math.floor((low + high) / 2)
      const candidate = text.slice(0, mid) + ellipsis
      if (ctx.measureText(candidate).width <= maxContentWidth) low = mid + 1
      else high = mid
    }
    return text.slice(0, Math.max(0, low - 1)) + ellipsis
  }

  // 属性
  if (Array.isArray(element.attributes)) {
    element.attributes.forEach(attr => {
      const vis = getVisibilitySymbol(attr.visibility)
      const raw = `${vis} ${attr.name || ''}: ${attr.type || ''}`
      const text = truncate(raw)
      ctx.fillText(text, x + contentPaddingX, cursorY)
      cursorY += 16
    })
  }

  // 分隔线（如果有方法）
  if (Array.isArray(element.methods) && element.methods.length > 0) {
    cursorY += 4
    ctx.beginPath()
    ctx.moveTo(x, cursorY)
    ctx.lineTo(x + width, cursorY)
    ctx.stroke()
    cursorY += 12
  }

  // 方法
  if (Array.isArray(element.methods)) {
    element.methods.forEach(method => {
      const vis = getVisibilitySymbol(method.visibility)
      const raw = `${vis} ${method.name || ''}(): ${method.returnType || ''}`
      const text = truncate(raw)
      ctx.fillText(text, x + contentPaddingX, cursorY)
      cursorY += 16
    })
  }

  ctx.restore()
}

/**
 * 绘制连接中的线条
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} connectionStart - 连接起始点
 * @param {Object} connectionEnd - 连接结束点
 */
export function drawConnectingLine(ctx, connectionStart, connectionEnd) {
  ctx.save()
  ctx.strokeStyle = '#1890ff'
  ctx.lineWidth = 2
  ctx.setLineDash([5, 5])
  
  // 绘制连线预览
  ctx.beginPath()
  ctx.moveTo(connectionStart.x, connectionStart.y)
  ctx.lineTo(connectionEnd.x, connectionEnd.y)
  ctx.stroke()
  
  // 绘制起点和终点标记
  const markerSize = 4
  ctx.fillStyle = '#1890ff'
  ctx.beginPath()
  ctx.arc(connectionStart.x, connectionStart.y, markerSize, 0, 2 * Math.PI)
  ctx.fill()
  
  ctx.beginPath()
  ctx.arc(connectionEnd.x, connectionEnd.y, markerSize, 0, 2 * Math.PI)
  ctx.fill()
  
  ctx.restore()
}

/**
 * 绘制状态图元素
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} element - 元素对象
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 */
export function drawStateElement(ctx, element, x, y, width, height) {
  // 根据状态类型选择不同的样式
  if (element.stateType === 'initial') {
    // 初始状态 - 黑色实心圆
    ctx.beginPath()
    ctx.arc(x + width/2, y + height/2, Math.min(width, height)/3, 0, Math.PI * 2)
    ctx.fillStyle = '#000000'
    ctx.fill()
    return
  } else if (element.stateType === 'final') {
    // 最终状态 - 双重圆（外圆内圆）
    const radius = Math.min(width, height)/3
    
    // 外圆
    ctx.beginPath()
    ctx.arc(x + width/2, y + height/2, radius, 0, Math.PI * 2)
    ctx.strokeStyle = '#000000'
    ctx.lineWidth = 2
    ctx.stroke()
    
    // 内圆
    ctx.beginPath()
    ctx.arc(x + width/2, y + height/2, radius * 0.7, 0, Math.PI * 2)
    ctx.fillStyle = '#000000'
    ctx.fill()
    return
  } else if (element.stateType === 'choice') {
    // 选择状态 - 菱形
    ctx.beginPath()
    ctx.moveTo(x + width/2, y)
    ctx.lineTo(x + width, y + height/2)
    ctx.lineTo(x + width/2, y + height)
    ctx.lineTo(x, y + height/2)
    ctx.closePath()
    
    // 填充渐变色
    const gradient = ctx.createLinearGradient(x, y, x + width, y + height)
    gradient.addColorStop(0, '#ffe58f')
    gradient.addColorStop(1, '#ffd666')
    ctx.fillStyle = gradient
    ctx.fill()
    
    // 绘制边框
    ctx.strokeStyle = '#faad14'
    ctx.lineWidth = 2
    ctx.stroke()
    return
  } else if (element.stateType === 'composite') {
    // 复合状态 - 带有内部区域的圆角矩形
    drawRoundedRectangle(ctx, x, y, width, height, 12)
    
    // 填充渐变色
    const gradient = ctx.createLinearGradient(x, y, x, y + height)
    gradient.addColorStop(0, '#f0f5ff')
    gradient.addColorStop(1, '#d6e4ff')
    ctx.fillStyle = gradient
    ctx.fill()
    
    // 绘制边框
    ctx.strokeStyle = '#2f54eb'
    ctx.lineWidth = 2
    ctx.stroke()
    
    // 绘制标题栏
    const titleHeight = 30
    ctx.fillStyle = '#2f54eb'
    ctx.fillRect(x, y, width, titleHeight)
    
    // 绘制标题文本
    ctx.fillStyle = '#ffffff'
    ctx.font = 'bold 14px Arial'
    ctx.textAlign = 'center'
    ctx.textBaseline = 'middle'
    ctx.fillText(element.name || element.label || '', x + width / 2, y + titleHeight / 2)
    
    // 绘制内部区域分隔线
    ctx.beginPath()
    ctx.moveTo(x, y + titleHeight)
    ctx.lineTo(x + width, y + titleHeight)
    ctx.strokeStyle = '#2f54eb'
    ctx.lineWidth = 1
    ctx.stroke()
    
    return
  }
  
  // 普通状态 - 圆角矩形
  drawRoundedRectangle(ctx, x, y, width, height, 12)
  
  // 填充渐变色
  const gradient = ctx.createLinearGradient(x, y, x, y + height)
  gradient.addColorStop(0, '#e6f7ff')
  gradient.addColorStop(1, '#bae7ff')
  ctx.fillStyle = gradient
  ctx.fill()
  
  // 绘制边框
  ctx.strokeStyle = '#1890ff'
  ctx.lineWidth = 2
  ctx.stroke()
  
  // 绘制标题文本
  ctx.fillStyle = '#333333'
  ctx.font = 'bold 14px Arial'
  ctx.textAlign = 'center'
  ctx.textBaseline = 'middle'
  ctx.fillText(element.name || element.label || '', x + width / 2, y + height / 3)
  
  // 绘制内容区域
  if (element.description) {
    ctx.fillStyle = '#666666'
    ctx.font = '12px Arial'
    ctx.textAlign = 'center'
    ctx.textBaseline = 'middle'
    ctx.fillText(element.description, x + width / 2, y + height * 2/3)
  }
}

/**
 * 绘制用例图元素
 * @param {CanvasRenderingContext2D} ctx - Canvas上下文
 * @param {Object} element - 元素对象
 * @param {number} x - x坐标
 * @param {number} y - y坐标
 * @param {number} width - 宽度
 * @param {number} height - 高度
 */
export function drawUseCaseElement(ctx, element, x, y, width, height) {
  if (element.usecaseType === 'actor') {
    // 角色 - 人形图标
    const centerX = x + width / 2
    const centerY = y + height / 2
    const size = Math.min(width, height) * 0.6
    
    // 绘制头部
    ctx.beginPath()
    ctx.arc(centerX, centerY - size * 0.3, size * 0.2, 0, Math.PI * 2)
    ctx.fillStyle = '#ff7875'
    ctx.fill()
    ctx.strokeStyle = '#d9363e'
    ctx.lineWidth = 2
    ctx.stroke()
    
    // 绘制身体
    ctx.beginPath()
    ctx.moveTo(centerX, centerY - size * 0.1)
    ctx.lineTo(centerX, centerY + size * 0.4)
    ctx.strokeStyle = '#ff7875'
    ctx.lineWidth = 3
    ctx.stroke()
    
    // 绘制手臂
    ctx.beginPath()
    ctx.moveTo(centerX - size * 0.3, centerY)
    ctx.lineTo(centerX + size * 0.3, centerY)
    ctx.strokeStyle = '#ff7875'
    ctx.lineWidth = 3
    ctx.stroke()
    
    // 绘制腿部
    ctx.beginPath()
    ctx.moveTo(centerX, centerY + size * 0.4)
    ctx.lineTo(centerX - size * 0.2, centerY + size * 0.6)
    ctx.moveTo(centerX, centerY + size * 0.4)
    ctx.lineTo(centerX + size * 0.2, centerY + size * 0.6)
    ctx.strokeStyle = '#ff7875'
    ctx.lineWidth = 3
    ctx.stroke()
    
    // 绘制角色名称
    ctx.fillStyle = '#333333'
    ctx.font = 'bold 12px Arial'
    ctx.textAlign = 'center'
    ctx.textBaseline = 'top'
    ctx.fillText(element.name || element.label || '', centerX, y + height + 5)
    
  } else if (element.usecaseType === 'system') {
    // 系统边界 - 圆角矩形
    drawRoundedRectangle(ctx, x, y, width, height, 15)
    
    // 填充渐变色
    const gradient = ctx.createLinearGradient(x, y, x, y + height)
    gradient.addColorStop(0, '#f6ffed')
    gradient.addColorStop(1, '#d9f7be')
    ctx.fillStyle = gradient
    ctx.fill()
    
    // 绘制边框
    ctx.strokeStyle = '#52c41a'
    ctx.lineWidth = 2
    ctx.stroke()
    
    // 绘制系统名称
    ctx.fillStyle = '#333333'
    ctx.font = 'bold 14px Arial'
    ctx.textAlign = 'center'
    ctx.textBaseline = 'middle'
    ctx.fillText(element.name || element.label || '', x + width / 2, y + height / 2)
    
  } else {
    // 用例 - 椭圆
    const centerX = x + width / 2
    const centerY = y + height / 2
    const radiusX = width / 2 - 5
    const radiusY = height / 2 - 5
    
    ctx.beginPath()
    ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, Math.PI * 2)
    
    // 填充渐变色
    const gradient = ctx.createRadialGradient(centerX, centerY, 0, centerX, centerY, radiusX)
    gradient.addColorStop(0, '#fff2e8')
    gradient.addColorStop(1, '#ffd8bf')
    ctx.fillStyle = gradient
    ctx.fill()
    
    // 绘制边框
    ctx.strokeStyle = '#fa8c16'
    ctx.lineWidth = 2
    ctx.stroke()
    
    // 绘制用例名称
    ctx.fillStyle = '#333333'
    ctx.font = 'bold 12px Arial'
    ctx.textAlign = 'center'
    ctx.textBaseline = 'middle'
    ctx.fillText(element.name || element.label || '', centerX, centerY)
  }
}

